/**
 *  目标： 我写用户列表的过程中，发现，跟其它页面的逻辑差不多，只是数据的不同
 *          想法： 把逻辑封装复用 ，提高工作效率
 * 
 *  如何封装？
 *      封装逻辑
 *          入参，出参(返回值)
 *              入参：逻辑中变化的东西
 *              出参：需要对外暴露的数据
 * 
 *      分析：
 *          入参： 数据在变，本质是不同的请求函数 ， 搜索用到的参数
 *          出参：请求回来的数据 ， 分页的数据(pageSize,pageNum,total)
 * 
 */

import { CancelTokenSource } from "axios";
import { reactive, ref, toRefs, watch } from "vue"

interface IResult {
    list: any[];
    total: number;
}

/**
 * 封装好的 表格增删改查的 hook(组合式函数)
 * @param fetchCallback 请求用的函数
 * @param searchParams 搜索携带的参数
 * @returns { list , pageNum , pageSize ,total , fetch} list 是请求回来的数组 ， pageNum,pageSize,total 是分页数据 ， fetch 是手动发请求的函数
 */
export default function useTable<T extends IResult>(fetchCallback: (params?: any) => RSP<T>, searchParams: Object) {
    //  ... todoe
    // 声明一个响应式的数据，是表格中要渲染的数组
    const list = ref<T['list']>([])
    const total = ref(0)

    const queryParams = reactive({
        pageNum: 1, pageSize: 10
    })

    // 在全局定义一个source对象，方便我们在 watch 里面使用它来取消请求
    let source: CancelTokenSource;
    // 定义一个变量，标记 请求是否正在进行
    let getting = false;

    // 一开始就要请求数据
    let fetch = () => {
        getting = true;
        fetchCallback({ ...queryParams, ...searchParams }).then((res) => {
            if (res.code === 200) {
                // 把数据存起来
                list.value = res.data.list
                total.value = res.data.total;
            }
        }).finally(() => {
            getting = false;
        })
    }
    fetch();

    // 当pageNum和pageSize变化，要更新数据
    let { pageNum, pageSize } = toRefs(queryParams)
    watch([pageNum, pageSize], (newVal, oldVal) => {
        // 如果获取表格数据的请求正在进行，就把上一个请求取消
        if (getting) {
            getting = false;
            // axios取消上一个请求
            source.cancel();
        }
        // 把上一个取消后，再发送下一个请求
        fetch()
    },)


    return {
        // 请求回来的数据,
        list,
        pageNum,
        pageSize,
        total,
        // 对外提供一个用来 手动发请求的数据
        fetch
    }
}